﻿/**	lx_assert.h
 *	----	Create Time Stamp:	--2005-09-17 02:48:41--
 *-----------------------------------------------------------------------------
 *	Mean	:用于调试目的而使用
 *	Author	:Nick Shallery	(nicknide@gmail.com)
 *	Version	:1.0.20.22	(2009-10-15 23:52:50)
 *-----------------------------------------------------------------------------
**/	/*YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.*/


#if			!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
#define		__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__

#if			!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)
	#include	"../lolix_cfg.h"
#endif	//	!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)

#if			!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	"../lolix_macro.h"
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)


#include	<stdarg.h>

#define		LOLIX_DEF__STATIC_ASSERT(r)			__LOLIX_DEF__STATIC_ASSERT_0(__COUNTER__, (r))
#define		LOLIX_DEF__CANNT_COPY_LOLI			__LOLIX_DEF__CANNT_COPY_LOLI

#define		LOLIX_DEF__STATIC_OUT_PUT_INT(number)			__LOLIX_DEF__STATIC_OUT_PUT_INT(number, __COUNTER__)



namespace lolix{namespace toy{namespace lx_assert{
#pragma warning(push, 4)
	template<int out_put_number, int>class static_out_put_int{public:static_out_put_int(void){int print_int = out_put_number;}};
#pragma warning(pop)
}}}


#define		__LOLIX_DEF__STATIC_ASSERT_0(l, r)		__LOLIX_DEF__STATIC_ASSERT_1(LOLIX_DEF__LINK_SYMBOL(__lolix__static_assert__, l), (r))
#define		__LOLIX_DEF__STATIC_ASSERT_1(n, r)		typedef struct{char __no_used[r?1:-1];}n

#define		__LOLIX_DEF__STATIC_OUT_PUT_INT(number, li)	__LOLIX_DEF__STATIC_OUT_PUT_INT_01(number, li, LOLIX_DEF__LINK_SYMBOL(__nick__toy__static_assert__, li))
#define		__LOLIX_DEF__STATIC_OUT_PUT_INT_01(number, li, name)							\
class name																		\
{																				\
	void func(void)																\
	{																			\
		::lolix::toy::lx_assert::static_out_put_int<number, li> static_int;		\
	}																			\
}


#if			LOLIX_CFG__IS_USE_ASSERT

#if			!defined(LOLIX_DEF__LOLIX_ASSERT)
	#define		LOLIX_DEF__LOLIX_ASSERT						LOLIX_DEF__LOLIX_ASSERT_EX(2)
#endif	//	!defined(LOLIX_DEF__LOLIX_ASSERT)

#define	LX_ASSERT_PROC	/**/

#include	<wchar.h>
	extern "C" __declspec(dllimport)	void __stdcall DebugBreak(void);

	#define		__LOLIX_DEF__CANNT_COPY_LOLI	__CANNT_COPY_LOLI__00__( LOLIX_DEF__LINK_SYMBOL(__lolix_cannt_copy_tunk__, __COUNTER__) )
	#define		__CANNT_COPY_LOLI__00__(name)	__CANNT_COPY_LOLI__01__( LOLIX_DEF__LINK_SYMBOL(name, ___) )
	#define		__CANNT_COPY_LOLI__01__(name)	__CANNT_COPY_LOLI__02__( LOLIX_DEF__LINK_SYMBOL(name, __LINE__) )
	#define		__CANNT_COPY_LOLI__02__(name)	__CANNT_COPY_LOLI__03__( name, LOLIX_DEF__LINK_SYMBOL(__lx_obj__, name) )
	#define		__CANNT_COPY_LOLI__03__(cname, oname)		\
class	cname{public: LOLIX_INLINE_CALL cname(void){} LOLIX_INLINE_CALL	~cname(void){}private: LOLIX_INLINE_CALL	cname(const cname&){*(int*)0 = 0;}; LOLIX_INLINE_CALL	cname& operator = (const cname& o){*(int*)0 = 0;return *this;};}oname

	namespace lolix{namespace toy{namespace lx_assert{
		class lolix_trace_class
		{
		public:
			LOLIX_INLINE_CALL static const lolix_trace_class get_trace_class(void){return lolix_trace_class();}
			LX_ASSERT_PROC const lolix_trace_class lolix_trace(const char* fmt, ...)const;
			LX_ASSERT_PROC const lolix_trace_class lolix_trace(const wchar_t* fmt, ...)const;
		};

		class lolix_assert_class
		{
		public:
			//typedef	lolix_break_class reflect_obj;
			LX_ASSERT_PROC lolix_assert_class(const wchar_t* fl, const wchar_t* func, int line, int level);
			LX_ASSERT_PROC lolix_assert_class(const char* fl, const char* func, int line, int level);
			template<typename _B>	inline void do_assert(_B b, const char* fmt, ...){va_list v_list; va_start(v_list, fmt); if ( !b ) _do_assert(fmt, 1, v_list);}
			template<typename _B>	inline void do_assert(_B b, const wchar_t* fmt, ...){va_list v_list; va_start(v_list, fmt); if ( !b ) _do_assert(fmt, 0, v_list);}
			enum { ASSERT_BUF_SIZE = 64 };
		private:
			LX_ASSERT_PROC void _do_assert(const void* fmt, bool bchar, va_list);
			char buf[ASSERT_BUF_SIZE/*+4*/];
		};

		class lolix_thread_zone_class
		{
			mutable	unsigned int _thread_id;
		public:
			LOLIX_INLINE_CALL	lolix_thread_zone_class(void):_thread_id(0){}
			LOLIX_INLINE_CALL	void bind_new(void)const{ _thread_id = 0; }
			LX_ASSERT_PROC	bool	check(void)const;
		};

		class lolix_thread_guard
		{
			mutable	unsigned int	_thread_id;
			mutable	long			_enter_cnt;
		public:
			LOLIX_INLINE_CALL	lolix_thread_guard(void): _thread_id(0), _enter_cnt(0){}
			LX_ASSERT_PROC	bool enter(void)const;
			LX_ASSERT_PROC	bool leave(void)const;
		};
	}}}
	#define	LOLIX_DEF__LOLIX_ASSERT_EX(level)			__LOLIX_DEF___LOLIX_ASSERT_EX_MAKE_NAME(level, LOLIX_DEF__LINK_SYMBOL(__debug_lolix_assert_t_class_with_macro__, __COUNTER__))
	#define	__LOLIX_DEF___LOLIX_ASSERT_EX_MAKE_NAME(level, oname)							__LOLIX_DEF___LOLIX_ASSERT_EX_MAKE_NAME_WITH_NAME(level, oname, LOLIX_DEF__LINK_SYMBOL(oname, __obj))


	#define	__LOLIX_DEF___LOLIX_ASSERT_EX_MAKE_NAME_WITH_NAME(level, oname, no_used)	static ::lolix::toy::lx_assert::lolix_assert_class oname\
														(__FILE__, __FUNCTION__, __LINE__, level);oname.do_assert

	#define		THREAD_ZONE								::lolix::toy::lx_assert::lolix_thread_zone_class

	#define		TOUCH_THREAD_ZONE(tz)		do{ LOLIX_DEF__LOLIX_ASSERT(tz.check(), L"多个线程访问单线程函数"); }while(0)	//	断言 tz 仅出现在当前线程上下文
	#define		RENEW_THREAD_ZONE(tz)		do{	tz.bind_new(); } while(0)										//	清掉 tz 的线程上下文环境

	#define		THREAD_GUARD							::lolix::toy::lx_assert::lolix_thread_guard
	#define		LOLIX_DEF__ENTER_THREAD_GUARD(tg)	do{ LOLIX_DEF__LOLIX_ASSERT(tg.enter(), L"线程守护冲突"); }while(0)
	#define		LOLIX_DEF__LEAVE_THREAD_GUARD(tg)	do{ LOLIX_DEF__LOLIX_ASSERT(tg.leave(), L"线程守护冲突"); }while(0)


#else	/*	LOLIX_CFG__IS_USE_ASSERT	*/
	#define	__LOLIX_DEF__CANNT_COPY_LOLI
	#define	LOLIX_DEF__LOLIX_ASSERT			__PUSH_AND_DISABLE_WARNING(4127)if(0)__POP_WARNING()
	#define	THREAD_ZONE						LOLIX_DEF__LINK_SYMBOL(/,/)
	#define	TOUCH_THREAD_ZONE(tz)			NULL_OPT
	#define	RENEW_THREAD_ZONE(tz)			NULL_OPT
	#define	LOLIX_DEF__LOLIX_ASSERT_EX(v)	if(0)

	#define	THREAD_GUARD					LOLIX_DEF__LINK_SYMBOL(/,/)
	#define	LOLIX_DEF__ENTER_THREAD_GUARD(tg)	NULL_OPT
	#define	LOLIX_DEF__LEAVE_THREAD_GUARD(tg)	NULL_OPT

#endif	/*	LOLIX_CFG__IS_USE_ASSERT	*/



#endif	//	!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
